﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml;
using System.Xml.Linq;
using System.Xml.XPath;

namespace Parallel.Translate
{
    /// <summary>
    /// xml注释文档
    /// </summary>
    public sealed class XmlTree
    {
        private readonly FileInfo _file;
        private readonly XDocument _docs;
        private readonly ITranslate _translator;
        private readonly IEnumerable<XElement> _eles;

        /// <summary>
        /// 创建给定翻译器的注释文档对象
        /// </summary>
        /// <param name="file"></param>
        /// <param name="translator"></param>
        public XmlTree(FileInfo file, ITranslate translator)
        {
            if (!file.Exists)
                throw new FileNotFoundException(file.FullName);
            _file = file;
            _docs = XDocument.Load(file.FullName);
            _eles = _docs.Root.XPathSelectElements("members/member/*");
            _translator = translator;
        }

        /// <summary>
        /// 释译文档
        /// </summary>
        /// <returns></returns>
        public async Task TranslateAsync()
        {
            try
            {
                // 并行有序遍历元素集合逐个调用翻译处理
                var tasks = _eles.AsParallel().AsOrdered().Select(i => TranslateAsync(i));
                await Task.WhenAll(tasks);
                await _translator.TranslateAsync(null);
                //var list = new List<Task>();
                //Parallel.ForEach(_eles, ele => list.Add(TranslateAsync(ele)));
                //await Task.WhenAll(list.Where(i => i != null));

            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);

            }
        }

        /// <summary>
        /// 翻译xml元素
        /// </summary>
        /// <param name="element"></param>
        /// <returns></returns>
        private async Task TranslateAsync(XElement element)
        {
            string result;
            if (element.IsEmpty)
            {
                return;
            }
            else
            {
                if (!element.HasElements)
                {
                    var text = await _translator.TranslateAsync(element.Value);
                    result = Format(text);
                }
                else
                {
                    var texts = new List<string>();
                    var builder = new StringBuilder();
                    foreach (var node in element.Nodes())
                    {
                        switch (node.NodeType)
                        {
                            case XmlNodeType.Text:
                                builder.Append($"{node.ToString(SaveOptions.None)} ");
                                break;
                            case XmlNodeType.Element:
                                builder.Append($" {{{texts.Count}}} ");
                                texts.Add(node.ToString());
                                break;
                            default:
                                break;
                        }
                    }
                    var text = await _translator.TranslateAsync(builder.ToString());
                    result = string.Format(Format(text), texts.ToArray());
                }
                try
                {
                    var resultElement = XElement.Parse($"<para>{result}</para>\r\n", LoadOptions.PreserveWhitespace);
                    element.AddFirst(resultElement);
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.Message);
                }
            }
        }
        /// <summary>
        /// 格式化文本
        /// </summary>
        /// <param name="text"></param>
        /// <returns></returns>
        private string Format(string text)
        {
            if (text.Contains('<') || text.Contains('>') || text.Contains('"'))
                return text.Replace("<", "&lt;").Replace(">", "&gt;").Replace("\"", "&quot;");
            else
                return text;
        }
        /// <summary>
        /// 保存xml文件
        /// </summary>
        public void Save()
        {
            File.Copy(_file.FullName, $"{_file.FullName}.bak", true);
            _docs.Save(_file.FullName);
        }
    }
}
